package utwente.sem.eindopdracht;
import java.util.Observable;

/**
 * Een Robot is een Object aan een AssemblageLijn welke één stap in het fabricageproces van een 
 * Product kan uitvoeren. Een Robot kan aan nul of één AssemblageLijn tegelijk gekoppeld zijn.
 * 
 * @author Richard Heijblom & Mark Wienk
 *
 */
public class Robot extends Observable implements Runnable {
	//STATES
	public static final int STATUS_IDLE = 0;
	public static final int STATUS_WAITING = 1;
	public static final int STATUS_PAUSE0 = 2;
	public static final int STATUS_PAUSE1 = 3;
	public static final int STATUS_RUNNING = 4;
	public static final int STATUS_ERROR = 5;

	private int status;
	private int id;
	private String instructie;
	private Exemplaar exemplaar;
	
	/**
	 * @clientCardinality *
	 * @supplierCardinality 0..1
	 */
	private AssemblageLijn assemblageLijn;
	
	/**
	 * Een Robot is een Object aan een AssemblageLijn welke één stap in het fabricageproces van een 
	 * Product kan uitvoeren. Een Robot kan aan nul of één AssemblageLijn tegelijk gekoppeld zijn.
	 * @param id - id nummer van de Robot.
	 * @param instructie - de beschrijving van de stap van de Robot
	 * @param assemblageLijn - de assemblageLijn waaraan de Robot gekoppeld is 
	 */
	public Robot(int id, String instructie, AssemblageLijn assemblageLijn){
		this.id = id;
		this.instructie = instructie;
		this.status = STATUS_IDLE;
		this.setAssemblageLijn(assemblageLijn);
		assemblageLijn.addRobot(this);
	}
	
	/**
	 * Stel de stap beschrijving van de Robot in.
	 * @param instructie
	 */
	public void setInstructie(String instructie) {
		this.instructie = instructie;
	}
	
	/**
	 * Verkrijg de stap beschrijving van de huidige Robot.
	 * @return beschrijving van de stap (String).
	 */
	public String getInstructie() {
		return this.instructie;
	}
	
	/**
	 * Verkrijg de ingestelde AssemblageLijn van de Robot.
	 * @return de ingestelde AssemblageLijn
	 */
	public AssemblageLijn getAssemblageLijn() {
		return this.assemblageLijn;
	}
	
	/**
	 * Stel een AssemblageLijn in bij de Robot.
	 * @param assemblageLijn
	 */
	public void setAssemblageLijn(AssemblageLijn assemblageLijn) {
		this.addObserver(assemblageLijn);
		this.assemblageLijn = assemblageLijn;
		//TODO: Check of de statusverandering legaal is (aan de hand van het State Diagram).
		if(assemblageLijn != null) { 
			this.status = STATUS_WAITING;
		}
		else {
			this.status = STATUS_IDLE;
		}
	}
	
	/**
	 * Stel het Exemplaar waar de Robot uitvoeringen op doet in
	 * @param exemplaar
	 */
	public void setExemplaar(Exemplaar exemplaar) {
		this.exemplaar = exemplaar;
	}
	
	/**
	 * Verkrijg het Exemplaar waar de Robot mee bezig is
	 * @return het huidige Exemplaar
	 */
	public Exemplaar getExemplaar() {
		return this.exemplaar;
	}
	
	/**
	 * Verkrijg de ingstelde status
	 * @return de ingestelde status (int)
	 */
	public int getStatus() {
		return status;
	}
	
	/**
	 * Stel de status van de Robot in.
	 * @param status statusnummer(int)
	 */
	public void setStatus(int status) {
		this.status = status;
		this.setChanged();
		this.notifyObservers();
	}
	
	/**
	 * Verkrijg het ID van de robot.
	 * @return het ID
	 */
	public int getId() {
		return this.id;
	}
	
	/**
	 * Stel het ID van de robot in.
	 * @param id
	 */
	public void setId(int id) {
		this.id = id;
	}
	
	/**
	 * Pauzeer een Robot.
	 */
	public void pauzeer() {
		if(this.status == STATUS_WAITING) {
			this.setStatus(STATUS_PAUSE0);
		}
		else {
			//TODO:Check of Robot niet in error state zit (is de state change legaal?)
			this.setStatus(STATUS_PAUSE1); 
		}
	}
	
	/**
	 * Voer een stap uit in het productieproces van een Product.
	 * @throws InterruptedException 
	 */
	public boolean voerStapUit() {
		try {
			//TODO: Implementatie van het assembleren
			/* 
			 * Gebruik de instructie uit de stap van de blauwdruk icm de Ton die aan het 
			 * component gekoppeld is. Haal een exemplaar uit de Ton en assembleer die 
			 * aan het Exemplaar in uitvoering zoals in de instructie staat uitgelegd.
			 */
			Thread.sleep(5000);
			return true;
		} catch (Exception e) {
			Tui.getUI().toonBericht("De uitvoering van de stap is onderbroken");
			this.setStatus(STATUS_ERROR);
			return false;
		}
	}
	
	/**
	 * Verkrijg de informatie van de Robot voor weergave in een lijst.
	 */
	public String toString() {
		return "Status: " + getStatus() + ", Instructie: " + getInstructie();
	}

	@Override
	/**
	 * Start de robot
	 */
	public void run() {
		if(this.exemplaar == null) return;
		if(this.status == STATUS_PAUSE0){
			this.setStatus(STATUS_WAITING);
		} else {
			//TODO:Check of Robot niet in error state zit (is de state change legaal?)
			this.setStatus(STATUS_RUNNING); 
			if(voerStapUit()) this.setStatus(STATUS_WAITING);
		}		
	}
}
